package com.cyy.daijia.customer.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.cyy.daijia.common.execption.CException;
import com.cyy.daijia.common.result.ResultCodeEnum;
import com.cyy.daijia.coupon.client.CouponFeignClient;
import com.cyy.daijia.customer.client.CustomerInfoFeignClient;
import com.cyy.daijia.customer.service.OrderService;
import com.cyy.daijia.dispatch.client.NewOrderFeignClient;
import com.cyy.daijia.driver.client.DriverInfoFeignClient;
import com.cyy.daijia.map.client.LocationFeignClient;
import com.cyy.daijia.map.client.MapFeignClient;
import com.cyy.daijia.map.client.WxPayFeignClient;
import com.cyy.daijia.model.entity.order.OrderInfo;
import com.cyy.daijia.model.enums.OrderStatus;
import com.cyy.daijia.model.form.coupon.UseCouponForm;
import com.cyy.daijia.model.form.customer.ExpectOrderForm;
import com.cyy.daijia.model.form.customer.SubmitOrderForm;
import com.cyy.daijia.model.form.map.CalculateDrivingLineForm;
import com.cyy.daijia.model.form.order.OrderInfoForm;
import com.cyy.daijia.model.form.payment.CreateWxPaymentForm;
import com.cyy.daijia.model.form.payment.PaymentInfoForm;
import com.cyy.daijia.model.form.rules.FeeRuleRequestForm;
import com.cyy.daijia.model.vo.base.PageVo;
import com.cyy.daijia.model.vo.customer.ExpectOrderVo;
import com.cyy.daijia.model.vo.dispatch.NewOrderTaskVo;
import com.cyy.daijia.model.vo.driver.DriverInfoVo;
import com.cyy.daijia.model.vo.map.DrivingLineVo;
import com.cyy.daijia.model.vo.map.OrderLocationVo;
import com.cyy.daijia.model.vo.map.OrderServiceLastLocationVo;
import com.cyy.daijia.model.vo.order.CurrentOrderInfoVo;
import com.cyy.daijia.model.vo.order.OrderBillVo;
import com.cyy.daijia.model.vo.order.OrderInfoVo;
import com.cyy.daijia.model.vo.order.OrderPayVo;
import com.cyy.daijia.model.vo.payment.WxPrepayVo;
import com.cyy.daijia.model.vo.rules.FeeRuleResponseVo;
import com.cyy.daijia.order.client.OrderInfoFeignClient;
import com.cyy.daijia.rules.client.FeeRuleFeignClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
    private final CouponFeignClient couponFeignClient;
    private final MapFeignClient mapFeignClient;
    private final FeeRuleFeignClient feeRuleFeignClient;
    private final OrderInfoFeignClient orderInfoFeignClient;
    private final NewOrderFeignClient newOrderFeignClient;
    private final DriverInfoFeignClient driverInfoFeignClient;
    private final LocationFeignClient locationFeignClient;
    private final CustomerInfoFeignClient customerInfoFeignClient;
    private final WxPayFeignClient wxPayFeignClient;
    @Override
    public ExpectOrderVo expectOrder(ExpectOrderForm expectOrderForm) {
        //传递经纬度，通过地图获得距离，系统获得时间，通过规则获得费用
        CalculateDrivingLineForm calculateDrivingLineForm = BeanUtil.copyProperties(expectOrderForm, CalculateDrivingLineForm.class);
        //不进行if判断了
        DrivingLineVo data = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();
        FeeRuleRequestForm feeRuleRequestForm =new FeeRuleRequestForm();
        feeRuleRequestForm.setDistance(data.getDistance());
        feeRuleRequestForm.setStartTime(new Date());
        //虽然写了等待时间的逻辑，但是没有却设定死了
        feeRuleRequestForm.setWaitMinute(0);
        FeeRuleResponseVo feeRuleResponseVo = feeRuleFeignClient.calculateOrderFee(feeRuleRequestForm).getData();
        ExpectOrderVo expectOrderVo = new ExpectOrderVo();
        expectOrderVo.setDrivingLineVo(data);
        expectOrderVo.setFeeRuleResponseVo(feeRuleResponseVo);
        return expectOrderVo;
    }

    @Override
    public Long submitOrder(SubmitOrderForm submitOrderForm) {
        CalculateDrivingLineForm calculateDrivingLineForm = BeanUtil.copyProperties(submitOrderForm, CalculateDrivingLineForm.class);
        DrivingLineVo drivingLineVo = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();
        FeeRuleRequestForm  feeRuleRequestForm =new FeeRuleRequestForm();
        feeRuleRequestForm.setDistance(drivingLineVo.getDistance());
        feeRuleRequestForm.setStartTime(new Date());
        //虽然写了等待时间的逻辑，但是没有却设定死了
        feeRuleRequestForm.setWaitMinute(0);
        FeeRuleResponseVo feeRuleResponseVo = feeRuleFeignClient.calculateOrderFee(feeRuleRequestForm).getData();

        OrderInfoForm orderInfoForm = BeanUtil.copyProperties(submitOrderForm, OrderInfoForm.class);
        //预估里程
        orderInfoForm.setExpectDistance(drivingLineVo.getDistance());
        orderInfoForm.setExpectAmount(feeRuleResponseVo.getTotalAmount());
        Long orderId = orderInfoFeignClient.saveOrderInfo(orderInfoForm).getData();
        //TODD 添加订单定时任务
        NewOrderTaskVo newOrderTaskVo = BeanUtil.copyProperties(orderInfoForm, NewOrderTaskVo.class);
        newOrderTaskVo.setOrderId(orderId);
        newOrderTaskVo.setExpectTime(drivingLineVo.getDuration());
        newOrderTaskVo.setCreateTime(new Date());
        Long jobId = newOrderFeignClient.addAndStartTask(newOrderTaskVo).getData();
        return orderId;
    }

    @Override
    public Integer getOrderStatus(Long orderId) {
        return orderInfoFeignClient.getOrderStatus(orderId).getData();
    }

    @Override
    public CurrentOrderInfoVo searchCustomerCurrentOrder(Long customerId) {
        return orderInfoFeignClient.searchCustomerCurrentOrder(customerId).getData();
    }

    @Override
    public OrderInfoVo getOrderInfo(Long orderId, Long customerId) {
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        if(orderInfo.getCustomerId()==customerId){
            DriverInfoVo driverInfoVo=null;
            if(null != orderInfo.getDriverId()) {
                driverInfoVo = driverInfoFeignClient.getDriverInfo(orderInfo.getDriverId()).getData();
            }
            OrderBillVo orderBillVo = null;
            if (orderInfo.getStatus().intValue() >= OrderStatus.UNPAID.getStatus().intValue()) {
                orderBillVo = orderInfoFeignClient.getOrderBillInfo(orderId).getData();
            }
            OrderInfoVo orderInfoVo = BeanUtil.copyProperties(orderInfo, OrderInfoVo.class);
            orderInfoVo.setOrderId(orderInfo.getId());
            orderInfoVo.setOrderBillVo(orderBillVo);
            orderInfoVo.setDriverInfoVo(driverInfoVo);
            return orderInfoVo;
        }
        throw new CException(ResultCodeEnum.ILLEGAL_REQUEST);
    }

    @Override
    public DriverInfoVo getDriverInfo(Long orderId, Long customerId) {
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        if(orderInfo.getCustomerId()!=customerId){
            throw new CException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        return driverInfoFeignClient.getDriverInfo(orderInfo.getDriverId()).getData();
    }

    @Override
    public OrderLocationVo getCacheOrderLocation(Long orderId) {
        return locationFeignClient.getCacheOrderLocation(orderId).getData();
    }

    @Override
    public OrderServiceLastLocationVo getOrderServiceLastLocation(Long orderId) {
        return locationFeignClient.getOrderServiceLastLocation(orderId).getData();
    }

    @Override
    public PageVo findCustomerOrderPage(Long customerId, Long page, Long limit) {
        return orderInfoFeignClient.findCustomerOrderPage(customerId, page, limit).getData();
    }

    @Override
    public WxPrepayVo createWxPayment(CreateWxPaymentForm createWxPaymentForm) {
        if(createWxPaymentForm.getCustomerId()==null) createWxPaymentForm.setCustomerId(1L);
        //1.获取订单支付相关信息
        OrderPayVo orderPayVo = orderInfoFeignClient.getOrderPayVo(createWxPaymentForm.getOrderNo(), createWxPaymentForm.getCustomerId()).getData();
        //判断是否在未支付状态
        if (orderPayVo.getStatus().intValue() != OrderStatus.UNPAID.getStatus().intValue()) {
            throw new CException(ResultCodeEnum.ILLEGAL_REQUEST);
        }

        //2.获取乘客微信openId
        String customerOpenId = customerInfoFeignClient.getCustomerOpenId(orderPayVo.getCustomerId()).getData();

        //3.获取司机微信openId
        String driverOpenId = driverInfoFeignClient.getDriverOpenId(orderPayVo.getDriverId()).getData();

        //4.封装微信下单对象，微信支付只关注以下订单属性
        //4.处理优惠券
        BigDecimal couponAmount = null;
        //支付时选择过一次优惠券，如果支付失败或未支付，下次支付时不能再次选择，只能使用第一次选中的优惠券（前端已控制，后端再次校验）
        if (null == orderPayVo.getCouponAmount() && null != createWxPaymentForm.getCustomerCouponId() && createWxPaymentForm.getCustomerCouponId() != 0) {
            UseCouponForm useCouponForm = new UseCouponForm();
            useCouponForm.setOrderId(orderPayVo.getOrderId());
            useCouponForm.setCustomerCouponId(createWxPaymentForm.getCustomerCouponId());
            useCouponForm.setOrderAmount(orderPayVo.getPayAmount());
            useCouponForm.setCustomerId(createWxPaymentForm.getCustomerId());
            couponAmount = couponFeignClient.useCoupon(useCouponForm).getData();
        }

        //5.更新账单优惠券金额
        //支付金额
        BigDecimal payAmount = orderPayVo.getPayAmount();
        if (null != couponAmount) {
            Boolean isUpdate = orderInfoFeignClient.updateCouponAmount(orderPayVo.getOrderId(), couponAmount).getData();
            if (!isUpdate) {
                throw new CException(ResultCodeEnum.DATA_ERROR);
            }
            //当前支付金额 = 支付金额 - 优惠券金额
            payAmount = payAmount.subtract(couponAmount);
        }
        PaymentInfoForm paymentInfoForm = new PaymentInfoForm();
        paymentInfoForm.setCustomerOpenId(customerOpenId);
        paymentInfoForm.setDriverOpenId(driverOpenId);
        paymentInfoForm.setOrderNo(orderPayVo.getOrderNo());
        paymentInfoForm.setAmount(payAmount);
        paymentInfoForm.setContent(orderPayVo.getContent());
        paymentInfoForm.setPayWay(1);

        WxPrepayVo wxPrepayVo = wxPayFeignClient.createWxPayment(paymentInfoForm).getData();
        return wxPrepayVo;
    }

    @Override
    public Boolean queryPayStatus(String orderNo) {
        return wxPayFeignClient.queryPayStatus(orderNo).getData();
    }
}
